import { toFixAndFloat } from "@/lib/util";
import { IntUnion } from "@/types/typeTool";
import { BaseProps } from "@/types/baseProps";
import { Progress } from "antd";
import dayjs from "dayjs";
import { ReactNode, useCallback, useEffect, useRef, useState } from "react";
/**0-100整数类型 */
type IntPercent = IntUnion<0, 100>;
interface TimerShowProps extends BaseProps {
  /**计时的开始时间。默认是当前 */
  startTime?: dayjs.ConfigType;
  /**计时的持续时间，单位s */
  totalTime: number;
  /**本组件全部UI的渲染函数，默认是一个进度条 */
  render?: (nowTime: number, totalTime: number) => ReactNode;
  /**倒计时结束后要做的事 */
  onSuccess?: () => any;
  /**每隔多久刷新一次数据，默认1000ms */
  duration?: number;
  /**刷新数据时，想触发的函数 */
  onProgress?: (percent: number, nowTime: number, totalTime: number) => any;
  /**每个进度整数，想触发的函数
   * @example 比如想进度75的时候触发，就 { 75: ()=>{xxx} }
   */
  onIntProgress?: Partial<Record<IntPercent, (nowTime: number, totalTime: number) => any>>;
}

/**一个倒计时组件 */
export default function TimerShow({
  totalTime,
  startTime = Date.now(),
  render,
  className,
  style,
  onSuccess,
  duration = 1000,
  onProgress,
  onIntProgress,
}: TimerShowProps) {
  const [time, setTime] = useState(0); //当前已经经过的时间

  /**上一次的进度 */
  const prePercent = useRef(-1);
  /**触发整数进度函数 */
  const triggerInt = (nowTime: number, percent: number) => {
    if (onIntProgress) {
      /**当前进度的整数 */
      const nowInt = Math.floor(percent);

      //如果上次进度比整数小，当前进度比整数大，说明该触发了
      if (prePercent.current < nowInt && percent >= nowInt) {
        onIntProgress[nowInt as IntPercent]?.(nowTime, totalTime);
      }

      prePercent.current = percent;
    }
  };
  /**获得当前百分比 */
  const getPercent = useCallback(
    (nowTime: number) => {
      return toFixAndFloat((nowTime / totalTime) * 100);
    },
    [totalTime]
  );

  useEffect(() => {
    let t: NodeJS.Timeout;
    const getTime = () => {
      /**当前时间 */
      const nowTime = dayjs().diff(dayjs(startTime), "second"); //当前时间减去开始时间
      setTime(nowTime);
      /**当前百分比 */
      const percent = getPercent(nowTime);
      onProgress?.(percent, nowTime, totalTime);

      triggerInt(nowTime, percent);

      if (nowTime >= totalTime) {
        clearInterval(t);
        onSuccess?.();
      }
    };
    getTime();
    t = setInterval(getTime, duration);
    return () => {
      clearInterval(t);
    };
  }, []);

  return render ? render(time, totalTime) : <Progress percent={getPercent(time)} className={className} style={style} />;
}
